package com.dynamic.mybatis.core.parser.field;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.dynamic.mybatis.core.enums.Type;
import com.dynamic.mybatis.core.metadata.MappedStatementFieldValidator;
import com.dynamic.mybatis.core.metadata.MappedStatementMetaField;
import com.dynamic.mybatis.core.session.DynamicSqlSession;
import com.dynamic.mybatis.core.utils.BeanUtils;
import org.apache.ibatis.ognl.Ognl;
import org.apache.ibatis.ognl.OgnlException;

import java.time.temporal.ChronoField;
import java.time.temporal.Temporal;
import java.util.*;

public abstract class DynamicMappedStatementFieldFormatter extends DynamicMappedStatementFieldValidator {

    public DynamicMappedStatementFieldFormatter(DynamicSqlSession dynamicSqlSession) {
        super(dynamicSqlSession);
    }

    public Object format(List<MappedStatementMetaField> field, Object rootParameter, Object parameter) {
        if (CollectionUtils.isEmpty(field)) {
            return parameter;
        }
        return format(field.get(0), rootParameter, parameter);
    }

    public Object format(MappedStatementMetaField field, Object rootParameter, Object parameter) {
        if (field == null) {
            return parameter;
        }
        return format(field, null, rootParameter, parameter);
    }

    /**
     * @param field         字段信息
     * @param type          类型，用来解决field类型为数组，泛型问题
     * @param rootParameter 原生参数值
     * @param parameter     当前参数值
     * @return
     */
    public Object format(MappedStatementMetaField field, String type, Object rootParameter, Object parameter) {
        MappedStatementFieldValidator validator = field.getValidator();
        if (!field.isVisible()) {
            return null;
        }

        boolean primitiveCheck = validator != null && parameter != null;

        type = StringUtils.isNotBlank(type) ? type : field.getType();

        if (primitiveCheck && Type.DATE_TIME_TYPES.contains(type)) {//日期、时间

            if (parameter instanceof Date) {
                return DateUtil.format((Date) parameter, validator.getDatePattern());
            } else if (parameter instanceof Temporal) {
                return DateUtil.format(LocalDateTimeUtil.of(((Temporal) parameter).getLong(ChronoField.MILLI_OF_SECOND)), validator.getDatePattern());
            } else if (parameter instanceof java.sql.Date) {
                return DateUtil.format(LocalDateTimeUtil.of(((java.sql.Date) parameter).toLocalDate().getLong(ChronoField.MILLI_OF_SECOND)), validator.getDatePattern());
            }
            return parameter;

        } else if (primitiveCheck && CollectionUtils.isNotEmpty(validator.getEnums())) {//枚举

            Object value = validator.getEnums().get(Objects.toString(parameter));
            return value != null ? value : parameter;

        } else if (Objects.equals(type, Type.StandardType.STRUCT.javaTypeAlias)) { //对象
            if (CollectionUtils.isEmpty(field.getChildren())) {
                return parameter;
            }
            Map parameterMap = BeanUtils.beanToMap(parameter);

            if (CollectionUtils.isEmpty(parameterMap)) {
                return parameter;
            }
            for (MappedStatementMetaField child : field.getChildren()) {

                //属性值为数组时，废弃使用泛型，否则递归调用无法进入字段类型为数组的判断程序
                String childType = Objects.equals(child.getType(), Type.StandardType.ARRAY.javaTypeAlias) ? null : child.getGenericType();
                Object result = format(child, childType, rootParameter, parameterMap.get(child.getField()));
                if (result != null) {
                    if (child.getValidator() != null && CollectionUtils.isNotEmpty(child.getValidator().getEnums())) {
                        parameterMap.put(child.getField() + "Text", result);
                        parameterMap.put(child.getField(), parameterMap.get(child.getField()));
                    } else {
                        parameterMap.put(child.getField(), result);
                    }
                }
                if (!child.isVisible()) {
                    parameterMap.remove(child.getField());
                }
            }

        } else if (Objects.equals(type, Type.StandardType.ARRAY.javaTypeAlias)) {//数组

            if (!(parameter instanceof Collection)) {
                return parameter;
            }

            List list = ((List) parameter);
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i) == null) {
                    continue;
                }
                Object result = format(field, field.getGenericType(), rootParameter, list.get(i));
                if (result != null) {
                    ((List) parameter).set(i, result);
                }
            }
        }
        if (validator != null && validator.getOgnlExpression() != null) { //ognl校验
            try {
                return Ognl.getValue(validator.getOgnlExpression(), rootParameter);
            } catch (Exception e) {
                return parameter;
            }
        }
        return parameter;
    }

    public static void main(String[] args) throws OgnlException {
        Map context = new HashMap();
        context.put("a", 1);
        Object value = Ognl.getValue("a", context);


        Map context1 = new HashMap();
        List<Map<String, Object>> ls = new ArrayList();

        Map fc = new HashMap();
        fc.put("a", "A01");
        fc.put("b", "B01");
        fc.put("c", "C01");
        ls.add(fc);

        Map fc2 = new HashMap();
        fc2.put("a", "A02");
        fc2.put("b", "B02");
        fc2.put("c", "C02");
        ls.add(fc2);

        context1.put("list1", ls);

        String val = "B02";
        Object obj = Ognl.getValue(Ognl.parseExpression("list1.{?#this.a.equals(\"A01\") || #this.b==" + val + "}"), context1);
        System.out.println(obj);
    }


}
